dojo.provide("dojot.util.AutoComplete");
dojo.require("dojox.html.styles");
dojo.require("dojo.io.script");

dojo.declare("dojot.util.AutoComplete",null,{
    //引用文本输入框的元素
    textInput:null,
    //保存orgId的input框，暂时不需要了
    orgInput:null,
    //这个是提示容器的className
    scClassName:'suggest_c',
    
    //这个是选中的className
    ssClassName:'suggest_s',
    
    //这个是我们生成的建议的内容的cache
    suggestions:null,
    
    //我们请求服务的url
    serverUrl:"http://192.168.1.165:8080/solr/select/?version=2.2&start=0&rows=10&indent=on&wt=json",
    
    //是否全文匹配,我们默认从开头匹配
    matchAnywhere:false,
    //学校还是公司的类型
    searchType:"",
    //需要显示结果的数量
    count:10,
    //发起请求的timeout,如果在延时时间内，新的请求到来，则取消先前的timeout
    suggestTimeout:null,
    //延迟请求的时间
    delay:200,
    //这个记录的是用户通过选择来得到的值
    searchValue:"",
    //新加的，记录用户通过键盘输入的值，
    userInputValue:"",
    //提示容器的显示状态
    _isShowingNow:false,
    
    //保存住当前的对象，为以后catch也可以使用做准备
    items:[],
    //记录住当前高亮的元素索引
    selectIndex:-1,
    
    //缓存的查询结果
    cached:
        {
            c:{},
            s:{}
        },
    //这个主要记录了鼠标的状态。主要是为了解决直接响应mouseover事件，如果，我们鼠标放到了提示列表的区域中，当我们们
    //的提示列表出现的时候，正好显示到鼠标的位置的时候就会相应mouseover事件，这样的话，就会让用户正在输入的时候，可能
    //由于提示列表的出现，而导致mouseover的事件的产生，从而导致用户在输入的文本框中，出现了提示的文字，从而导致错误。
    //这样的话，可以先一个状态。默认是0，当时0的时候，才相应我们的mouseover时间，当是1的时候，可以相应我们的move事件
    mouseStatus:0,
    //记录住container的style因为这个要反复使用
    containerStyle:null,
     
    //隐藏容器的timeout,如果在新的显示来临之前，还没有隐藏，则取消隐藏
    hiddenContainerTimeout:null,
    //在ie6下面需要用这个iframe进行select的遮挡
    selectIframe:null,
    constructor: function(obj){
console.time("create");
        
        obj.textInput = ((typeof obj.textInput) === 'string') ? dojo.byId(obj.textInput) : obj.textInput;
        //obj.orgInput = ((typeof obj.orgInput) === 'string') ? dojo.byId(obj.orgInput) : obj.orgInput;

        dojo.mixin(this,obj);
        
        //初始化一些值，不过是我们上面声明的一部分，由于一个页面可能存在多个实例化的类，所以需要重新赋值
        this.selectIndex = -1;
        this.searchValue = this.userInputValue = this.textInput.value;
    },
    _createIframe: function(/*String*/fname){
    	/**
    	 * 为了ie6下面遮挡select做的
    	 */
        var cframe = null;
        var ifrstr = dojo.isIE ? '<iframe name="'+fname+'">' : 'iframe';
        cframe = dojo.doc.createElement(ifrstr);
        with(cframe){
            name = fname;
            setAttribute("name", fname);
            id = fname;
        }
        dojo.body().appendChild(cframe);
        window[fname] = cframe;
        return cframe;  
    },
        
    postscript:function(){
        var that = this;
        dojo.attr(this.textInput,"autocomplete","off");
       
        dojo.connect(this.textInput,"onkeypress",dojo.hitch(this,"_onKeypress"));
        dojo.connect(this.textInput,"onblur",function(){
            this.hiddenContainerTimeout = setTimeout(function() {
                that.hideSuggestContainer()
            }, that.delay);    
        });
        if(dojo.isIE == 6){
              this.selectIframe = this._createIframe("selectIframe");
        }
        this.suggestContainer = dojo.create("ul",{},dojo.body());
        console.log(this.suggestContainer);
     
        dojo.addClass(this.suggestContainer,this.scClassName);
        
      	this.initStyle();
        this.hideSuggestContainer();
        this.containerStyle = dojo.style(this.suggestContainer);
        this._setPosition();

        setTimeout(function(){
            dojo.connect(window,"resize",dojo.hitch(that,"_setPosition"));
        },this.delay);
        window.setInterval(function(){
            //得到用户现在input里面的值
            var newValue = that.textInput.value;
            //if 这个值和准备用于搜索的值，也就是是通过上下选择器产生的值，不等的话，说明用户自己产生的值，
            //那么我们需要发起请求。
            if(that.searchValue != newValue){
                if(!that.hiddenContainerTimeout){
                    that.hiddenContainerTimeout = setTimeout(function(){
                         that.hideSuggestContainer();
                    },500);
                }
                if(that.suggestTimeout){
                    clearTimeout(that.suggestTimeout);
                }
                that.suggestTimeout = setTimeout(function(){
                      that._sendRequestForSuggestions()
                },that.delay);
                that.userInputValue = that.searchValue = newValue;
            }
        
        } ,10);
console.timeEnd("create");
    },
    initStyle:function(){
    	//可以被覆盖，如果有新的样式的话
    	//方法1:(1)先直接覆盖两个classname,(2)然后覆盖此方法。如果需要动态添加样式，可以在代码里面写，否则可以对这个进行空实现，然后再样式表里面加入同名的class
    	
    	//可以通过把样式内容传递进来，然后覆盖这个方法
    	this._addStyle("."+ this.scClassName,"display:none;font-size:13px;cursor:default;line-height:17px;border:1px solid black;z-index:99;background:white;position:absolute;margin:0;list-style:none;padding-left:0px;");
        //选中的option
        this._addStyle("."+ this.ssClassName,"background:#36c;color:white;");
    },
    _setPosition:function(){
        var scBorder = dojo._getBorderExtents(this.suggestContainer);
        //var scStyle = this.suggestContainer.style; 改成用dojo.style来做了
        //ul的元素的width是没有边框的宽度。所以我们需要减去边框的宽度。table元素没有这个问题
        var lt = this._getTopAndLeft(this.textInput);
        dojo.style(this.suggestContainer,{
        	left:lt.left+"px",
        	top:lt.top+this.textInput.offsetHeight-scBorder.t+"px",
        	width:this.textInput.offsetWidth-scBorder.w+"px"
        })
    },
    _getTopAndLeft:function(elem){
        var that = this;
        var tL = {};
        var top = 0,left = 0;
        top += elem.offsetTop 
        left += elem.offsetLeft;
        elem = elem.offsetParent;
        var calculator = function(elem){
            var topBorderWidth=0,leftBorderWidth=0;
            if(elem){
                if(elem.tagName.toUpperCase() != 'FIELDSET'){
                    //计算边框
                    var elemStyle = dojo.style(elem);
                    topBorderWidth = parseInt(elemStyle['borderTopWidth']);
                    leftBorderWidth = parseInt(elemStyle['borderLeftWidth']);

                    topBorderWidth = !isNaN(topBorderWidth) && topBorderWidth;
                    leftBorderWidth = !isNaN(leftBorderWidth) && leftBorderWidth;
                }
                top += (elem.offsetTop + topBorderWidth);
                left += (elem.offsetLeft + leftBorderWidth);
                elem = elem.offsetParent;
                calculator(elem)
            }else{
                return;
            }
        }
        calculator(elem);
        tL.top = top;
        tL.left = left;
        return  tL;
    },
    _onKeypress:function(evt){
        var dk = dojo.keys;
        this._setKeyChar(evt);
        var key = evt.charOrCode;
        var that = this;
        var isContainerVisible = this._isContainerVisible();
        switch(key){
            case dk.DOWN_ARROW:
                //如果现在没有显示出来提示框，则显示，前提是里面有数据
                if(!isContainerVisible){
                    this.showSuggestContainer();
                }else{
                    this._highlightOption(null,(this.selectIndex+1));
                }
                dojo.stopEvent(evt);
                break;
            case dk.UP_ARROW:
                if(!isContainerVisible){
                        this.showSuggestContainer();
                }else{
                       this._highlightOption(null,(this.selectIndex-1));
                }
                dojo.stopEvent(evt);
                break;
            case dk.ENTER:
                //处理用户回车事件，加入咱们自己的处理
                if(isContainerVisible){	
                    this.hideSuggestContainer();
                    //可能需要加表单提交事件,以后可以加hock方法，目前先不考虑
                }
                dojo.stopEvent(evt);
                break;
            case dk.ESCAPE:
                if(isContainerVisible){
                    this.hideSuggestContainer();
                    this._resumeInputValue();
                    this._clearOrgId();
                }
                break;	
        }
    },
    _sendRequestForSuggestions: function(){
        var that = this;
        if(!this.userInputValue || this.userInputValue.length <= 0){
            return;
        }
       // this._createSuggestions1();
        //return;
        var data = this._getDataFromCache(this.userInputValue);
        if(data){
            this._createSuggestions(data);
            return;
        }
        var req = {
            url: this.serverUrl,
            callbackParamName:'json.wrf',
            content: {
                 q: this._getSearchValue()
            },
            load: function(data){
                that._createSuggestions(data);
            },
            error: function(err){
                console.log(err);
                return;
            }
        };
        var deffered = dojo.io.script.get(req);   
    },
    _createSuggestions:function(data){
        
        this._addToCache(this.userInputValue,data);
        
        if(this.hiddenContainerTimeout){
            clearTimeout(this.hiddenContainerTimeout);
            this.hiddenContainerTimeout = null;
        }
       
        if(data){
            data = data.response.docs;
        }else{
            //test data
            data = [{orgName:[this.userInputValue + 'aa']},{orgName:[this.userInputValue + 'bb']},{orgName:[this.userInputValue+'cc']},{orgName:[this.userInputValue + 'dd']}];
        }
        console.log(this);       
        var that = this;
        this.clearSuggestContainer();
        dojo.forEach(data, function(item,index){
            var node = dojo.create("li", { innerHTML: item.orgName[0],id:parseInt(item.id)}, that.suggestContainer,"last");
            that.items.push(node);
            dojo.connect(node,"onmouseover",function(evt){
                if(that.mouseStatus)return;
                that._highlightOption(node,index);
            })
            dojo.connect(node,"onmousemove",function(evt){
                if(that.mouseStatus){
                    that.mouseStatus = 0;
                    that._highlightOption(node,index);
                }
            });
        });
        data.length > 0 ? this.showSuggestContainer() : that.hideSuggestContainer();
    },
    hideSuggestContainer:function(){
        if(this.hiddenContainerTimeout){
            window.clearTimeout(this.hiddenContainerTimeout);
            this.hiddenContainerTimeout=null
        }
        dojo.style(this.suggestContainer,{
            "display":"none"
        });
        this._hideSelectIframe();
    },
    _addToCache: function(userInputValue,data){
        this.cached[this.searchType][userInputValue] = data;
    },
    _getDataFromCache: function(userInputValue){
        return this.cached[this.searchType][userInputValue];
    },
    showSuggestContainer:function(){
        this.mouseStatus = 1;
        if(this.items.length > 0 ){
            dojo.style(this.suggestContainer,{
            "display":"block"
            }); 
        }
        this._showSelectIframe();
    },
    clearSuggestContainer:function(){
        //dojo.empty(this.suggestContainer);
        this.suggestContainer.innerHTML = "";
        this.items = [];
        this.selectIndex = -1;
    },
    _addStyle:(function(){
        var styleSheet = dojox.html.getDynamicStyleSheet("autocomplete");
        return function(styleName,styleBody){
            var styleContent = styleName + " { "+styleBody+" }";
            dojox.html.insertCssRule(styleName,styleBody,styleSheet);
        } ;    
    })(),
    _setKeyChar: function(evt){
        evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
        evt.charOrCode = evt.keyChar || evt.keyCode;
    },
    _highlightOption:function(item,index){
            //需要把上一个选中的元素的高亮给清除，然后重新设置当前选中元素。
            var highLlighted;
            if((highLlighted=this.getHighlightedOption())){
                dojo.removeClass(highLlighted,"suggest_s");
            }	
            var length = this.items.length;
            if(index < -1){
                index = index + length + 1;
            }else if(index == length){
                index = -1;
            }
            
            console.log("index aa-->"+index);
            this.selectIndex = index;	
            item = item || this.items[index];
            if(index < 0){	
                    this.searchValue = this.textInput.value = this.userInputValue;
                    //把orgId清空
                    this._clearOrgId();
            }else{
                if(item){
                    dojo.addClass(item,"suggest_s");
                    //dojo.attr(this.orgInput,"value",dojo.attr(item,"id"));
                    //如果是通过向上向下产生的input的值,则不需要进行在此搜索。
                    this.searchValue = this.textInput.value = item.innerHTML;
                    
                }
            }
    },
    getHighlightedOption: function(){
        if(this.selectIndex < 0){
            return null;
        }
        return this.items[this.selectIndex];
    },
    _clearOrgId: function(){
    	//暂时不需要
    	return;
        dojo.attr(this.orgInput,"value",""); 
    },
    _getSearchValue:function(){
        //凑成solar需要的数据
        return "orgName:"+this._filterSpace(this.userInputValue) + ' AND type:'+this.searchType;
    },
    _filterSpace: function(value){
        return value.replace(/[ ]+/g,"+");
    },
    _isContainerVisible: function(){
        return this.containerStyle['display'] == 'block';
    },
    _resumeInputValue: function(){
        //恢复input的值为用户最后输入的值
        this.textInput.value = this.userInputValue;
    },
    _showSelectIframe: function(){
        console.log('_showSelectIframe');
        if(!this.selectIframe)return;
        //if(dojo.isIE == 6){
            var sc = dojo.marginBox(this.suggestContainer);
                dojo.style(this.selectIframe,{
                   position : "absolute",
                   left :sc.l+'px',
                   top :sc.t + "px",
                   width:sc.w + 'px',
                   height:sc.h + 'px',
                   zIndex:0
            });
                
            console.log(this.selectIframe);
            console.log(dojo.style(this.selectIframe));
       // }
    },
    _hideSelectIframe:function(){
         if(!this.selectIframe)return;
         dojo.style(this.selectIframe,{
                   position : "absolute",
                   left :0+'px',
                   top :0 + "px",
                   width:0 + 'px',
                   height:0 + 'px',
                   zIndex:0
         });
    }
})